-- CIS 552, Mini-project
-- by Mike Gottlieb and Reilly Grant

-- |Utility functions we wish were in the Prelude, but aren't.
module Util where

import List

-- |Count the number of elements in a list satisfying a predicate.
countWith :: (a -> Bool) -> [a] -> Int
countWith p = length . filter p

-- |Check that the list contains elements where one is the successor of the 
--  last.
increasingByOne :: (Enum a, Eq a) => [a] -> Bool
increasingByOne [] = True
increasingByOne as = tail as == init (map succ as)

-- |Count the number of duplicate entries in a list and return a list of tuples
--  (element, # of duplicates).
countDups :: (Eq a) => [a] -> [(a, Int)]
countDups as = [(x, numberOf x) | x <- nub as]
               where numberOf x = countWith (x==) as

-- |Attempt to parse a String, returning Nothing if the parse fails.
readMaybe :: (Read a) => String -> Maybe a
readMaybe s = let read = reads s in
              case read of
                [] -> Nothing
                rs -> Just $ fst $ head rs

-- |Replace the nth element of a list with the given element.
replace :: Int -> a -> [a] -> [a]
replace _ _ [] = error "Cannot replace element of an empty list."
replace n e as = if n < 0 || n >= length as
                    then error "Bad list index"
                    else take n as ++ [e] ++ drop (n+1) as

-- |Perform monadic action if Maybe has a value, otherwise return unit.
maybeM :: (Monad m) => (a -> m b) -> Maybe a -> m (Maybe b)
maybeM f a = maybe (return Nothing) (justApply f) a
             where justApply f x = do r <- f x
                                      return $ Just r
